#!/usr/bin/env python3
# encoding: utf-8
# @Author: Aiden
# @Date: 2024/11/18
import time
import rclpy
import threading
from rclpy.node import Node
from std_msgs.msg import Int32, String, Bool
from std_srvs.srv import SetBool, Trigger, Empty
from geometry_msgs.msg import Twist  # 记得导入消息类型

from speech import awake
from speech import speech
from large_models.config import *
from large_models_msgs.srv import SetInt32



class VocalDetect(Node):
    def __init__(self, name):
        rclpy.init()
        super().__init__(name)

        self.running = True

        # 声明参数
        self.declare_parameter('awake_method', 'xf')
        self.declare_parameter('mic_type', 'mic6_circle')
        self.declare_parameter('port', '/dev/wonderecho')
        self.declare_parameter('enable_wakeup', True)
        self.declare_parameter('enable_setting', False)
        self.declare_parameter('awake_word', 'xiao3 huan4 xiao3 huan4')
        self.declare_parameter('mode', 1)

        self.awake_method = self.get_parameter('awake_method').value
        mic_type = self.get_parameter('mic_type').value
        port = self.get_parameter('port').value
        awake_word = self.get_parameter('awake_word').value
        enable_setting = self.get_parameter('enable_setting').value 
        self.enable_wakeup = self.get_parameter('enable_wakeup').value
        self.mode = int(self.get_parameter('mode').value)

        self.s_key_pressed = False


        if self.awake_method == 'xf':
            self.kws = awake.CircleMic(port, awake_word, mic_type, enable_setting)
        else:
            self.kws = awake.WonderEchoPro(port) 
        
        if self.awake_method == 'xf':
            self.asr = speech.RealTimeASR(log=self.get_logger())
        else:
            self.asr = speech.RealTimeASR(channel=1, log=self.get_logger())
        
        self.asr_pub = self.create_publisher(String, '~/asr_result', 1)
        self.wakeup_pub = self.create_publisher(Bool, '~/wakeup', 1)
        self.awake_angle_pub = self.create_publisher(Int32, '~/angle', 1)
        self.create_service(SetInt32, '~/set_mode', self.set_mode_srv)
        self.create_service(SetBool, '~/enable_wakeup', self.enable_wakeup_srv)
        self.create_subscription(String, '/keyboard_command', self.keyboard_callback, 10)
        threading.Thread(target=self.pub_callback, daemon=True).start()
        self.create_service(Empty, '~/init_finish', self.get_node_state)
        self.tts_text_pub = self.create_publisher(String, 'tts_node/tts_text', 1)  
        self.input_type = None
        self.get_logger().info('\033[1;32m%s\033[0m' % 'start')
        self.text_input = None

    def get_node_state(self, request, response):
        return response

    def record(self, mode, angle=None, ):
        self.get_logger().info('\033[1;32m%s\033[0m' % 'asr...')
        if self.input_type == 'voice':
            asr_result = self.asr.asr(model=asr_model)  # 开启录音并识别
            self.input_type = None
        elif self.input_type == 'text':
            timeout_sec = 10.0
            
            start_time = self.get_clock().now()
            rate = self.create_rate(10)  # 检查频率为 10Hz，即每 0.1 秒检查一次

            while (self.get_clock().now() - start_time).nanoseconds / 1e9 < timeout_sec:
                if self.text_input is not None:
                    asr_result = self.text_input
                    self.text_input = None
                    break
                rate.sleep()
            else:
                # 超时未获取到输入，可以选择赋空值或者跳过
                self.get_logger().warn("等待文本输入超时，跳过处理")
                msg = String()
                msg.data = "检测到非中文输入，请重新输入！"
                self.tts_text_pub.publish(msg)
                asr_result = None
            self.input_type = None

        if asr_result: 
            speech.play_audio(dong_audio_path)
            if self.awake_method == 'xf' and self.mode == 1: 
                msg = Int32()
                msg.data = int(angle)
                self.awake_angle_pub.publish(msg)
            asr_msg = String()
            asr_msg.data = asr_result
            self.asr_pub.publish(asr_msg)
            self.enable_wakeup = False
            self.get_logger().info('\033[1;32m%s\033[0m' % 'publish asr result:' + asr_result)
        else:
            self.get_logger().info('\033[1;32m%s\033[0m' % 'no voice detect')
            speech.play_audio(dong_audio_path)
            if mode != 3:
                speech.play_audio(no_voice_audio_path)

    def pub_callback(self):
        print('pub_callback starts working')
        if self.enable_wakeup and self.mode == 1:
            self.kws.start()
        while self.running:
            if self.enable_wakeup:
                if self.mode == 1:
                    if self.s_key_pressed:
                        print('current mode is : %d' % self.mode)
                        self.s_key_pressed = False  # 重置标志
                        self.wakeup_pub.publish(Bool(data=True))
                        speech.play_audio(wakeup_audio_path)  # 唤醒播放
                        self.record(self.mode)
                elif self.mode == 2:
                    print('current mode is : %d' % self.mode)
                    self.record(self.mode)
                    self.mode = 1
                elif self.mode == 3:
                    print('current mode is : %d' % self.mode)
                    self.record(self.mode)
                else:
                    print('current mode is null')
                    time.sleep(0.02)

            else:
                time.sleep(0.02)
        rclpy.shutdown()

    def enable_wakeup_srv(self, request, response):
        self.get_logger().info('\033[1;32m%s\033[0m' % ('enable_wakeup'))
        self.kws.start()
        self.enable_wakeup = request.data
        response.success = True
        return response 

    def set_mode_srv(self, request, response):
        self.get_logger().info('\033[1;32m%s\033[0m' % ('set_mode'))
        self.mode = int(request.data)
        if self.mode == 2:
            self.enable_wakeup = True
        response.success = True
        return response 
    
    def keyboard_callback(self, msg):
    # 检测是否符合自定义的“按下s”条件
        if msg.data.strip().lower() == 'v':
            self.get_logger().info("收到键盘 v 指令，语言模式执行")
            self.s_key_pressed = True
            self.input_type = 'voice'
        
        elif msg.data.strip().lower() == 'b':
            self.get_logger().info("收到键盘 b 指令，重新开始")
            self.enable_wakeup = True
        elif msg.data.strip().lower() == 't':
            self.get_logger().info("收到键盘 t 指令，文本模式执行")
            self.s_key_pressed = True
            self.input_type = "text"
        elif self.input_type == "text":
            text = msg.data
            is_all_chinese = True
            for ch in text:
                if '\u4e00' <= ch <= '\u9fff':  # 中文字符 Unicode 范围
                    self.get_logger().info("检测到中文输入: {}".format(ch))
                else:
                    self.get_logger().info("非中文输入: {}".format(ch))
                    msg = String()
                    msg.data = "检测到非中文输入，请重新输入！"
                    self.tts_text_pub.publish(msg)
                    is_all_chinese = False
            if is_all_chinese:
                self.text_input = text


        

def main():
    node = VocalDetect('vocal_detect')
    try:
        rclpy.spin(node)
    except KeyboardInterrupt:
        print('shutdown')
    finally:
        rclpy.shutdown() 

if __name__ == "__main__":
    main()
